//
//  BBImageView.m
//  BBCoverFlowTest
//
//  Created by ben smith on 3/10/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "BBImageView.h"
#import "BBTUIOCursor.h"



@implementation BBImageView
@synthesize directoryDepth;

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
			[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(blobEventsNotification:) name:@"BBTUIOCursors" object:nil];

			
			[self setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
			[self setupLayers];
			buttonsOutOfView = [[NSMutableArray alloc] init];
			buttonsInView = [[NSMutableArray alloc] init];
			[self setupButtons];
			[self setupMarkers];
			directoryDepth = 0;
			selected = -1;
			
        // Initialization code here.
    }
    return self;
}

-(void)setupLayers
{
	CALayer * root = [CALayer layer];
	//root.backgroundColor = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0);
	//root.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
	//root.borderWidth = 1.0;
	//root.opaque = YES;
	root.name = @"rootLayer";
	root.layoutManager = [CAConstraintLayoutManager layoutManager];
	
	[self setLayer:root];
	[self setWantsLayer:YES];
	
	bogusLayer = [[CALayer layer] retain];
	[root addSublayer:bogusLayer];
	
	// the central scrolling layer; this will contain the images
	bodyLayer = [CAScrollLayer layer];
	bodyLayer.name = @"bodyLayer";
	bodyLayer.scrollMode = kCAScrollHorizontally;
	bodyLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
	//	bodyLayer.borderColor = CGColorCreateGenericRGB(0.0, 0.5, 1.0, 0.5); // yellow
	//	bodyLayer.borderWidth = 1.0;
	
	[root addSublayer:bodyLayer];

}	

-(void)blobEventsNotification:(NSNotification*)note
{
	[CATransaction begin];
	[CATransaction setValue:[NSNumber numberWithFloat:0.0f]
									 forKey:kCATransactionAnimationDuration];
	
	NSInteger sublayerCount = [[markerLayer sublayers] count];
	float scaleX = NSWidth([self bounds]);
	float scaleY = NSHeight([self bounds]);
	NSInteger index = 0;
	NSArray * blobEvents = [note object];
	for (BBTUIOCursor * c in blobEvents) {
		NSPoint loc = [c position];
		loc.y = 1.0 - loc.y;
		loc.x *= scaleX;
		loc.y *= scaleY;
		if (index < sublayerCount) [[[markerLayer sublayers] objectAtIndex:index] setPosition:NSPointToCGPoint(loc)];
		index ++;
	}
	// any left?
	int i;
	for (i = index; i < sublayerCount; i++) {
		[[[markerLayer sublayers] objectAtIndex:i] setPosition:CGPointMake(-100, -100)];
	}	
	
	[CATransaction commit];
}


-(void)setupMarkers
{
	markerLayer = [CALayer layer];
	markerLayer.name = @"markerLayer";
	markerLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
	CGRect r;
	r.origin = CGPointZero;
	r.size.height = [self bounds].size.height;
	r.size.width = [self bounds].size.width;
	
	[markerLayer setFrame:r];
	[[self layer] insertSublayer:markerLayer above:bodyLayer];
	
	int i;
	for (i =0; i < 10; i++) {
		[markerLayer addSublayer:[self markerImageLayer]];
	}	
}

-(CALayer*)markerImageLayer
{
	CALayer * marker = [CALayer layer];
	
	CALayer * imageLayer = [CALayer layer];
	
	NSImage * fingerCircle  = [NSImage imageNamed:@"fingerCircle.png"];
	NSBitmapImageRep *bitrep = [NSBitmapImageRep imageRepWithData:[fingerCircle TIFFRepresentation]];
	[imageLayer setValue:bitrep forKey:@"bitrep"];
	CGRect r;
	r.origin = CGPointZero;
	r.size.height = [fingerCircle size].height;
	r.size.width = [fingerCircle size].width;
	[marker setFrame:r];
	[imageLayer setFrame:r];
	imageLayer.name = @"marker1";
	imageLayer.anchorPoint = CGPointMake(0.5, 0.5);
	imageLayer.contents = (id)[bitrep CGImage];
	imageLayer.zPosition = 10000;
	imageLayer.position = CGPointMake(r.size.width/2.0, r.size.height/2.0);
	
	[marker addSublayer:imageLayer];
	marker.position = CGPointMake(-100, -100);
	return marker;
}

-(void)setupButtons
{
	CGRect r;
	
	outOfButtonLayer = [[CALayer layer] retain];
	
	NSImage * outOf  = [NSImage imageNamed:@"outof.png"];
	NSBitmapImageRep *bitrep = [NSBitmapImageRep imageRepWithData:[outOf TIFFRepresentation]];
	[outOfButtonLayer setValue:bitrep forKey:@"bitrep"];
	r.origin = CGPointZero;
	r.size.height = [outOf size].height;
	r.size.width = [outOf size].width;
	[outOfButtonLayer setFrame:r];
	outOfButtonLayer.name = @"out";
	outOfButtonLayer.anchorPoint = CGPointMake(0.5, 0.5);
	outOfButtonLayer.contents = (id)[bitrep CGImage];
	outOfButtonLayer.zPosition = 10000;
	outOfButtonLayer.position = CGPointMake(NSMidX([self bounds]), -100);
	//outOfButtonLayer.borderWidth = 1.0;
	//outOfButtonLayer.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
	
	intoButtonLayer = [[CALayer layer] retain];
	NSImage * into  = [NSImage imageNamed:@"into.png"];
	bitrep = [NSBitmapImageRep imageRepWithData:[into TIFFRepresentation]];
	r.origin = CGPointZero;
	r.size.height = [into size].height;
	r.size.width = [into size].width;
	[intoButtonLayer setValue:bitrep forKey:@"bitrep"];
	[intoButtonLayer setFrame:r];
	intoButtonLayer.name = @"out";
	intoButtonLayer.anchorPoint = CGPointMake(0.5, 0.5);
	intoButtonLayer.contents = (id)[bitrep CGImage];
	intoButtonLayer.zPosition = 10000;
	intoButtonLayer.position = CGPointMake(NSMidX([self bounds]), -100);
	//	intoButtonLayer.borderWidth = 1.0;
	//intoButtonLayer.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
	
	lightBoxButtonLayer = [[CALayer layer] retain];
	NSImage * lb  = [NSImage imageNamed:@"lightboxView.png"];
	bitrep = [NSBitmapImageRep imageRepWithData:[lb TIFFRepresentation]];
	r.origin = CGPointZero;
	r.size.height = [into size].height;
	r.size.width = [into size].width;
	[lightBoxButtonLayer setFrame:r];
	[lightBoxButtonLayer setValue:bitrep forKey:@"bitrep"];
	lightBoxButtonLayer.name = @"lightBox";
	lightBoxButtonLayer.anchorPoint = CGPointMake(0.5, 0.5);
	lightBoxButtonLayer.contents = (id)[bitrep CGImage];
	lightBoxButtonLayer.zPosition = 10000;
	lightBoxButtonLayer.position = CGPointMake(NSMidX([self bounds]) + 45, -100);
	//	intoButtonLayer.borderWidth = 1.0;
	//intoButtonLayer.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
	
	
	circleLayoutButtonLayer = [[CALayer layer] retain];
	NSImage * circ  = [NSImage imageNamed:@"circleThing.png"];
	bitrep = [NSBitmapImageRep imageRepWithData:[circ TIFFRepresentation]];
	r.origin = CGPointZero;
	r.size.height = [into size].height;
	r.size.width = [into size].width;
	[circleLayoutButtonLayer setFrame:r];
	[circleLayoutButtonLayer setValue:bitrep forKey:@"bitrep"];
	circleLayoutButtonLayer.name = @"circle";
	circleLayoutButtonLayer.anchorPoint = CGPointMake(0.5, 0.5);
	circleLayoutButtonLayer.contents = (id)[bitrep CGImage];
	circleLayoutButtonLayer.zPosition = 10000;
	circleLayoutButtonLayer.position = CGPointMake(NSMidX([self bounds]) + 45, -100);
	//	intoButtonLayer.borderWidth = 1.0;
	//intoButtonLayer.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
	
	quitButtonLayer = [[CALayer layer] retain];
	NSImage * quit = [NSImage imageNamed:@"quit.png"];
	bitrep = [NSBitmapImageRep imageRepWithData:[quit TIFFRepresentation]];
	r.origin = CGPointZero;
	r.size.height = [into size].height;
	r.size.width = [into size].width;
	[quitButtonLayer setFrame:r];
	[quitButtonLayer setValue:bitrep forKey:@"bitrep"];
	quitButtonLayer.name = @"quit";
	quitButtonLayer.anchorPoint = CGPointMake(0.5, 0.5);
	quitButtonLayer.contents = (id)[bitrep CGImage];
	quitButtonLayer.zPosition = 10000;
	quitButtonLayer.position = CGPointMake(NSMidX([self bounds]) + 45, -100);
	//	intoButtonLayer.borderWidth = 1.0;
	//intoButtonLayer.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
	
	
	coverButtonLayer = [[CALayer layer] retain];
	NSImage * cover  = [NSImage imageNamed:@"coverView.png"];
	bitrep = [NSBitmapImageRep imageRepWithData:[cover TIFFRepresentation]];
	r.origin = CGPointZero;
	r.size.height = [into size].height;
	r.size.width = [into size].width;
	[coverButtonLayer setValue:bitrep forKey:@"bitrep"];
	[coverButtonLayer setFrame:r];
	coverButtonLayer.name = @"cover";
	coverButtonLayer.anchorPoint = CGPointMake(0.5, 0.5);
	coverButtonLayer.contents = (id)[bitrep CGImage];
	coverButtonLayer.zPosition = 10000;
	coverButtonLayer.position = CGPointMake(NSMidX([self bounds]), -100);
	//	intoButtonLayer.borderWidth = 1.0;
	//intoButtonLayer.borderColor = CGColorCreateGenericRGB(0.0, 1.0, 0.0, 0.5); // yellow
}

- (void)drawRect:(NSRect)rect {
    // Drawing code here.
}


-(void)handleButtonLayout
{
	CGFloat yOffset = NSMidY([self bounds]) + [[NSUserDefaults standardUserDefaults] floatForKey:@"BBButtonVerticalOffset"];
	CGFloat buttonSpacing = 50.0;
	NSInteger count = [buttonsInView count];
	CGPoint start = CGPointMake(NSMidX([self bounds]),yOffset);
	start.x -= (CGFloat)count/2.0 * buttonSpacing;
	for (CALayer * lyr in buttonsInView) {
		lyr.position = start;
		start.x += buttonSpacing;
	}
	CGPoint oot = CGPointMake(NSMidX([self bounds]),-100);
	if (yOffset > NSMidY([self bounds])) oot.y = NSMaxY([self bounds]) + 100;
	for (CALayer * lyr in buttonsOutOfView) {
		lyr.position = oot;
	}
}

-(CALayer*)layerWithName:(NSString*)name
{
	// first find the right layer
	for (CALayer * l in [bodyLayer sublayers]) {
		if ([l.name isEqualToString:name]) return l; 
	}
	return nil;
}

-(void)layoutSelected
{
	for (CALayer * layer in [bodyLayer sublayers]) {
		CGPoint p = layer.position;
		p.x = NSMidX([self bounds]);
		p.y = NSMidY([self bounds]);
		layer.position = p;
	}
}

-(void)layoutMarkers
{
	
}

-(void)loadMovie:(NSArray*)args
{
	[self setMovieContents:[args objectAtIndex:0] toLayer:[args objectAtIndex:1]];
}

-(void)imageFinishedLoading:(NSArray*)args
{
	[self setContents:[args objectAtIndex:0] mipMap:[args objectAtIndex:1] toLayer:[args objectAtIndex:2]];
}


-(void)setContents:(NSBitmapImageRep*)bitRep mipMap:(NSBitmapImageRep*)mipRep toLayer:(NSString*)name
{
	CALayer * thisLayer = [self layerWithName:name];
	if (thisLayer == nil) return;
	
	NSSize imageSize = [mipRep size];
	
	CALayer * imagelayer = [[thisLayer sublayers] objectAtIndex:0];
	CALayer * reflectionlayer = [[imagelayer sublayers] objectAtIndex:0];
	CGRect f = [imagelayer frame];
	f.size.width = imageSize.width;
	f.size.height = imageSize.height;
	
	[imagelayer setFrame:f];
	imagelayer.position = CGPointMake(125,125);
	
	f.origin = CGPointMake(0, -f.size.height);
	[reflectionlayer setFrame:f];
	
	imagelayer.contents = (id)[mipRep CGImage];
	reflectionlayer.contents = (id)[mipRep CGImage];
	
	[imagelayer setValue:bitRep forKey:@"bitRep"];
	[imagelayer setValue:mipRep forKey:@"mipRep"];
	
	[imagelayer setValue:(id)[bitRep CGImage] forKey:@"highRez"];
	[reflectionlayer setValue:(id)[bitRep CGImage] forKey:@"highRez"];
	
	[imagelayer setValue:(id)[mipRep CGImage] forKey:@"mipmap"];
	[reflectionlayer setValue:(id)[mipRep CGImage] forKey:@"mipmap"];
	
	CALayer * gradient = [[imagelayer sublayers] objectAtIndex:1];
	CGRect gFrame = [gradient frame];
	CGFloat xScale = imageSize.width/gFrame.size.width;
	CGFloat yScale = imageSize.height/gFrame.size.height;
	CATransform3D scale = CATransform3DMakeScale(xScale, -yScale, 1.0);
	gradient.transform = scale;
	f.origin.x -= .5;
	f.size.height += 1;
	f.size.width += 1;
	[gradient setFrame:f];
}



-(void)setMovieContentsToLayerNamed:(NSString*)name
{
	CALayer * thisLayer = [self layerWithName:name];
	if (thisLayer == nil) return;
	
	[self convertToMovieLayer:thisLayer];
}


-(CALayer*)photoLayer
{	
	CALayer * carrier = [CALayer layer];
	return carrier;
}

-(void)convertToMovieLayer:(CALayer*)aLayer
{
	return aLayer;	
}

-(void)addImageFiles:(NSArray*)fileNames;
{
	for (NSString * filename in fileNames) {
		BOOL isDirectory;
		if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDirectory]) {
			CALayer * l1 = [self photoLayer];	
			l1.name = filename;
			if (isDirectory) [l1 setValue:[NSNumber numberWithBool:YES] forKey:@"isDirectory"];
			if ([[NSImage imageFileTypes] containsObject:[filename pathExtension]]) {
				// nothing, this is the default
			} else {
				if ([[QTMovie movieFileTypes:QTIncludeTranslatableTypes] containsObject:[filename pathExtension]]) {
					[l1 setValue:[NSNumber numberWithBool:YES] forKey:@"isMovie"];
				}
			}
			[bodyLayer addSublayer:l1];		
		}
	}	
	// now kick off a thread to load the images
	[NSThread detachNewThreadSelector: @selector(loadImages:) toTarget:self withObject:fileNames];   
}

-(void)loadImages:(NSArray*)fileNames
{
  NSAutoreleasePool *apool=[[NSAutoreleasePool alloc] init];
	if (bitreps == nil) bitreps = [[NSMutableArray alloc] init];
	[bitreps removeAllObjects];
	
  NS_DURING 
	
	for (NSString * filename in fileNames) {		
		BOOL isDirectory;
		
		if ([[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDirectory]) {
			NSImage * anImage;
			
			if ([[QTMovie movieFileTypes:QTIncludeTranslatableTypes] containsObject:[filename pathExtension]]) {
				NSError * err = nil;
				QTMovie * movie = [QTMovie movieWithFile:filename error:&err];
				[movie setDelegate:self];
				// TODO: something with that ERROR!!
				[self performSelectorOnMainThread:@selector(setMovieContentsToLayerNamed:) withObject:filename waitUntilDone:NO];
				continue;
			}
			
			if (isDirectory) {
				NSString * firstPic = [self firstPicInDirectory:filename];
				if (firstPic == nil) continue;
				anImage  = [[NSImage alloc] initWithContentsOfFile:firstPic];									
			} else {
				anImage  = [[NSImage alloc] initWithContentsOfFile:filename];					
			}
			NSImage * mipmap = [self mipmapfromImage:anImage];
			
			NSBitmapImageRep * bitrep = [NSBitmapImageRep imageRepWithData:[anImage TIFFRepresentation]];
			NSBitmapImageRep * miprep = [NSBitmapImageRep imageRepWithData:[mipmap TIFFRepresentation]];
			//		[bitreps addObject:bitrep];	
			//		[bitreps addObject:miprep];	
			
			[self performSelectorOnMainThread:@selector(imageFinishedLoading:) withObject:[NSArray arrayWithObjects:bitrep,miprep, filename,nil] waitUntilDone:NO];
			
		}
	}	
	[self performSelectorOnMainThread:@selector(allImagesLoaded:) withObject:nil waitUntilDone:NO];
	
	NS_HANDLER
	[[NSAlert alertWithMessageText:@"Error with image load" defaultButton:@"Ok" alternateButton:nil otherButton:nil informativeTextWithFormat:[localException reason]] runModal];
	
	NS_ENDHANDLER
	[apool release];
}



-(void)allImagesLoaded:(id)sender
{
	
}


- (NSImage *)mipmapfromImage:(NSImage*)anImage
{
	float maxDim = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBMaxDimension"];
	float ratio = 1.0;
	NSSize newSize = [anImage size];
	if (newSize.height > newSize.width) {
		// then scale based on size
		ratio = maxDim/newSize.height;
	} else {
		ratio = maxDim/newSize.width;
	}
	newSize.height *= ratio;
	newSize.width *= ratio;
	
	NSImage *newImage = [[NSImage alloc] initWithSize:newSize];
	NSRect newRect = NSMakeRect(0.0, 0.0, newSize.width, newSize.height);
	
	[newImage lockFocus];
	[[NSGraphicsContext currentContext] setImageInterpolation: NSImageInterpolationHigh];	
	[anImage drawInRect:newRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1.0];
	[newImage unlockFocus];
	
	return [newImage autorelease];
}

-(NSString*)firstPicInDirectory:(NSString*)aDir
{
	NSArray * fileNames = [[NSFileManager defaultManager] directoryContentsAtPath:aDir];
	for (NSString * filename in fileNames) {
		if ([filename hasPrefix:@"."]) continue;
		return [aDir stringByAppendingPathComponent:filename];
	}
	return nil;
}

@end
